import Vue from 'vue';
import http, { AxiosError, AxiosResponse, AxiosRequestConfig } from 'axios';
import { Message, MessageBox } from 'element-ui';
import router from '@/router';
import { DialogModule } from '@/store/dialog';
import { DrawerModule } from '@/store/drawer';
import { AuthModule } from '@/store/auth';
import { $message, $notify } from '@/plugins/element';

const codeMessage: any = {
    200: '服务器成功返回请求的数据。',
    201: '新建或修改数据成功。',
    202: '一个请求已经进入后台排队（异步任务）。',
    204: '删除数据成功。',
    400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
    401: '用户没有权限（令牌、用户名、密码错误）。',
    403: '用户得到授权，但是访问是被禁止的。',
    404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
    405: '请求方法不被允许。',
    406: '请求的格式不可得。',
    410: '请求的资源被永久删除，且不会再得到的。',
    422: '当创建一个对象时，发生一个验证错误。',
    500: '服务器发生错误，请检查服务器。',
    502: '网关错误。',
    503: '服务不可用，服务器暂时过载或维护。',
    504: '网关超时。',
};

export enum ErrorShowType {
    SILENT = 0, // 不提示错误
    WARN_MESSAGE = 1, // 警告信息提示
    ERROR_MESSAGE = 2, // 错误信息提示
    NOTIFICATION = 4, // 通知提示
    REDIRECT = 9, // 页面跳转
}

const CancelToken = http.CancelToken;
const pending: any[] = [];

const errorHandler = (err: any) => {
    if (err.name === 'BizError') {

        console.log('message error', err);
        $message.error(err.message);
        return Promise.reject('error');
    }
    while (pending.length > 0) {
        pending.pop()('请求中断');
    }
    if (err.message === '请求中断') {
        return Promise.reject('请求中断');
    }

    const { response } = err;
    if (response && response.status) {
        const errorText = codeMessage[response.status] || response.statusText;
        const { status } = response;

        $notify.error({
            title: `请求错误 ${status}： ${err.config.url}`,
            message: errorText,
        });

        switch (status) {
            case 401:
                if (router.currentRoute.name !== 'login') {
                    AuthModule.logout();
                }
                break;
            case 403:
                if (router.currentRoute.name !== '403') {
                    DialogModule.close();
                    DrawerModule.close();
                    AuthModule.banPage({
                        route: router.currentRoute.name
                    });
                }
                break;
            default:
                break;
        }
    }

    if (!response) {
        $notify.error({
            title: '网络异常',
            message: '您的网络发生异常，无法连接服务器'
        });
    }
    return Promise.reject(err);
}

const h = http.create({
    baseURL: '/api',
    withCredentials: true,
});

h.interceptors.request.use((res) => {
    if (!res.cancelToken) {
        res.cancelToken = new CancelToken(function executor(c) {
            pending.push(c);
        });
    }
    if (AuthModule.token) {
        res.headers['Authorization'] = 'Basic ' + AuthModule.token;
    }
    res.message = true;
    return res;
})

h.interceptors.response.use((res: AxiosResponse) => {
    if (res.data.code) {
        const error = new Error(res.data.message);
        error.name = 'BizError';
        $message.error(res.data.message);

        return Promise.reject(error);
    }
    return res.data;
}, errorHandler);

// const request = {
//     get<T = any, R = AxiosResponse<T>>(uri: string, config?: AxiosRequestConfig): Promise<R> {
//         return h.get(uri, config);
//     },
//     post<T = any, R = AxiosResponse<T>>(uri: string, data?: any, config?: AxiosRequestConfig): Promise<R> {
//         return h.post(uri, data, config);
//     },
//     delete<T = any, R = AxiosResponse<T>>(uri: string, data?: any, config?: AxiosRequestConfig): Promise<R> {
//         return h.delete(uri, config);
//     }
// };

export default h;



Vue.prototype.$http = h;
